/*==================================================================================================
Starting implement OpenGL ES to T-engine

==================================================================================================*/

#include "Context.h"



/*==================================================================================================
*	DESCRIPTIONS:
*	Following function set the CURRENT drawing color
*
*	PARAMETER:
*		-
*	RETURNS:
*		-
==================================================================================================*/
GL_API void GL_APIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
	
	Context * context = getContext();
	
	if (context){
		context->Color.red = red;
		context->Color.green = green;
		context->Color.blue = blue;
		context->Color.alpha = alpha;
	}
}

GL_API void GL_APIENTRY glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz) {

	Context * context = getContext();
	
	if (context) {
		context->Normal.x = nx;
		context->Normal.y = ny;
		context->Normal.z = nz;
	}

}

GL_API void GL_APIENTRY glMultiTexCoord4f (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {

	Context * context = getContext();
	
	GLint index = target - GL_TEXTURE0;
	
	if (context) {
		context->TextureCoords[index].s = s;
		context->TextureCoords[index].t = t;
		context->TextureCoords[index].r = r;
		context->TextureCoords[index].q = q;
	}
}

GL_API void GL_APIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {

	Context * context = getContext();
	
	if (context) {
		context->VertexArray.pointer = (GLvoid *)pointer;
		context->VertexArray.type = type;//byte, short, fixed, float
		context->VertexArray.stride = stride;
		context->VertexArray.size = size; //2,3,4
	}
	
}

GL_API void GL_APIENTRY glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer) {
	
	Context * context = getContext();
	
	if (context) {
		context->NormalArray.pointer = (GLvoid *)pointer;
		context->NormalArray.type = type; //byte, short, fixed, float
		context->NormalArray.stride = stride;
		//context->NormalArray.size = 3; //Optional
	}
	
}

GL_API void GL_APIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {

	Context * context = getContext();
	
	if (context) {
		context->ColorArray.pointer = (GLvoid *)pointer;
		context->ColorArray.size = size; //always 4
		context->ColorArray.type = type; //ubyte, fixed, float
		context->ColorArray.stride = stride;
		
	}
	
}

GL_API void GL_APIENTRY glPointSizePointerOES (GLenum type, GLsizei stride, const GLvoid *pointer) {

	Context * context = getContext();
	
	if (context) {
		context->PointSizePointer.pointer = (GLvoid *)pointer;
		context->PointSizePointer.type = type; //fixed, float
		context->PointSizePointer.stride = stride;
		context->PointSizePointer.size = 1;
	}
}

GL_API void GL_APIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {

	Context * context = getContext();
	
	if (context) {
		context->TexCoordPointer.pointer = (GLvoid *)pointer;
		context->TexCoordPointer.type = type; //byte, short, fixed, float
		context->TexCoordPointer.size = size; //2,3,4
		context->TexCoordPointer.stride = stride;
	}
	
}

GL_API void GL_APIENTRY glEnableClientState (GLenum array) {

	Context * context = getContext();
	
	if (context) {
		switch (array) {
			case GL_TEXTURE_COORD_ARRAY:
				context->TexCoordArrayEnabled[context->ClientActiveTexture - GL_TEXTURE0] = GL_TRUE;
				break;

			case GL_COLOR_ARRAY:
				context->ColorArrayEnabled = GL_TRUE;
				break;

			case GL_NORMAL_ARRAY:
				context->NormalArrayEnabled = GL_TRUE;
				break;

			case GL_VERTEX_ARRAY:
				context->VertexArrayEnabled = GL_TRUE;
				break;

			case GL_POINT_SIZE_ARRAY_OES:
				context->PointSizeArrayEnabled = GL_TRUE;
				break;

			default:
				RecordError(GL_INVALID_ENUM);
				break;
		}
	}
	
}

GL_API void GL_APIENTRY glDisableClientState (GLenum array) {

	Context * context = getContext();
	
	if (context) {
		switch (array) {
			case GL_TEXTURE_COORD_ARRAY:
				context->TexCoordArrayEnabled[context->ClientActiveTexture] = GL_FALSE;
				break;

			case GL_COLOR_ARRAY:
				context->ColorArrayEnabled = GL_FALSE;
				break;

			case GL_NORMAL_ARRAY:
				context->NormalArrayEnabled = GL_FALSE;
				break;

			case GL_VERTEX_ARRAY:
				context->VertexArrayEnabled = GL_FALSE;
				break;

			case GL_POINT_SIZE_ARRAY_OES:
				context->PointSizeArrayEnabled = GL_FALSE;
				break;

			default:
				RecordError(GL_INVALID_ENUM);
				break;
		}
	}
	
}

GL_API void GL_APIENTRY glClientActiveTexture (GLenum texture) {

	Context * context = getContext();
	
	if (context) {
		context->ClientActiveTexture = texture - GL_TEXTURE0;
	}
	
}

GL_API void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count) {

	Context * context = getContext();
	int i;
	
	if (count < 0) {
		RecordError(GL_INVALID_VALUE);
		return;
	}

	if (!(context->VertexArrayEnabled)) {
		RecordError(GL_INVALID_OPERATION);
		return;
	}
	//Something goes here..
	
	for (i = first; i < count; i++){
		Transform ( i );
	}
	switch ( mode ){
		case GL_POINTS:
		break;
		
		case GL_LINE_STRIP:
		break;
		
		case GL_LINE_LOOP:
		break;
		
		case GL_LINES:
		break;
		
		case GL_TRIANGLE_STRIP:
		break;
		
		case GL_TRIANGLE_FAN:
		break;
		
		case GL_TRIANGLES:
		break;
		
	}

}

GL_API void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height) {

	Context * context = getContext();
	
	if (context) {
		context->ViewPort.ox = x + width/2; //x coordinate of center point of viewport
		context->ViewPort.oy = y + height/2; //y coordinate of center point of viewport
		context->ViewPort.px = width; //width of viewport
		context->ViewPort.py = height; //height of viewport
	}

}

GL_API void GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar) {

	Context * context = getContext();
	//zNear and zFar are clamped into [0,1]
	if (context) {
		context->DepthRange.zNear = zNear;
		context->DepthRange.zFar = zFar;
	}

}

GL_API void GL_APIENTRY glMatrixMode (GLenum mode) {

	Context * context = getContext();
	
	if (context) {
		if ( mode == GL_MODELVIEW ){
			context->Matrix.pCurrentMatrix = &(context->Matrix.ModelViewStack[context->Matrix.ModelViewStackPointer]);
		} else if (mode == GL_PROJECTION){
			context->Matrix.pCurrentMatrix = &(context->Matrix.ProjectionStack[context->Matrix.ProjectionStackPointer]);
		} else if (mode == GL_TEXTURE){
			context->Matrix.pCurrentMatrix = &(context->Matrix.TextureStack[context->ActiveTexture - GL_TEXTURE0][context->Matrix.TextureStackPointer[context->ActiveTexture - GL_TEXTURE0]]);
		}
	}
	
}

GL_API void GL_APIENTRY glLoadMatrixf (const GLfloat *m) {

	MatrixImport((GLfloat *)m);

//	Context * context = getContext();
	//replace the current active matrix
/*	
	if (context) {
		if(context->Matrix.CurrentMatrixMode == GL_PROJECTION)
			MatrixCopy(&(context->Matrix.ProjectionStack[context->Matrix.ProjectionStackPointer]),(GLfloat *)m);
		else if (context->Matrix.CurrentMatrixMode == GL_MODELVIEW )
			MatrixCopy(&(context->Matrix.ModelViewStack[context->Matrix.ModelViewStackPointer]),(GLfloat *)m);
		else if (context->Matrix.CurrentMatrixMode == GL_TEXTURE)
			MatrixCopy(&(context->Matrix.TextureStack[context->ActiveTexture - GL_TEXTURE0][context->Matrix.TextureStackPointer[context->ActiveTexture - GL_TEXTURE0]]),(GLfloat *)m);
	}
*/	

}

GL_API void GL_APIENTRY glMultMatrixf (const GLfloat *m) {

	Context * context = getContext();

	if (context) {
		MatrixMultiply(context->Matrix.pCurrentMatrix, (Vect4D *)m, context->Matrix.pCurrentMatrix);
	}
	
}

GL_API void GL_APIENTRY glLoadIdentity (void) {
	
	Context * context = getContext();
	//replace the current active matrix
	
	if (context) {
		MatrixImport((GLfloat*)&(context->Matrix.IdentityMatrix[0]));
	}
	
}

GL_API void GL_APIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z){

}

GL_API void GL_APIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z) {

	Context * context  = getContext();
	Matrix4x4 newMt = {1,0,0,x,
							 0,1,0,y,
							 0,0,1,z,
							 0,0,0,1};

	if (context) {
		MatrixImport((GLfloat*)&newMt);
	}
}

GL_API void GL_APIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z){

	Context * context  = getContext();
	Matrix4x4 newMt = {x,0,0,0,
							 0,y,0,0,
							 0,0,z,0,
							 0,0,0,1};

	if (context) {
		MatrixImport((GLfloat*)&newMt);
	}
}

GL_API void GL_APIENTRY glFrustumf (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar){

	Context * context  = getContext();
	Matrix4x4 newMt = { 2*zNear/(right-left),		 	0				  	,(right+left)/(right-left)	,	 	0		,
										0				 , 2*zNear/(top-bottom)	,(top+bottom)/(top-bottom)	,		0		,
										0				 ,			0					,-(zFar+zNear)/(zFar-zNear),-2*zFar*zNear/(zFar-zNear),
										0				 ,			0					,				-1					,		0						};

	if (context) {
		MatrixImport((GLfloat*)&newMt);
	}
}

GL_API void GL_APIENTRY glOrthof (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar){

	Context * context  = getContext();
	Matrix4x4 newMt = { 2/(right-left),			0		,			0		,-(right+left)/(right-left),
										0		,2/(top-bottom),			0		,-(top+bottom)/(top-bottom),
										0		,			0		,-2/(zFar-zNear),-(zFar+zNear)/(zFar-zNear),
										0		,			0		,			0		,				1					};

	if (context) {
		MatrixImport((GLfloat*)&newMt);
	}

}

GL_API void GL_APIENTRY glEnable (GLenum cap) {
	ToggleState(cap, GL_TRUE );
}

GL_API void GL_APIENTRY glDisable (GLenum cap) {
	ToggleState(cap, GL_FALSE );
}


GL_API void GL_APIENTRY glClipPlanef (GLenum plane, const GLfloat *equation){

	Context * context =  getContext();
	if (context){
		context->ClipPlane[plane - GL_CLIP_PLANE0].p1 = equation[0];
		context->ClipPlane[plane - GL_CLIP_PLANE0].p2 = equation[1];
		context->ClipPlane[plane - GL_CLIP_PLANE0].p3 = equation[2];
		context->ClipPlane[plane - GL_CLIP_PLANE0].p4 = equation[3];
	}
}

GL_API void GL_APIENTRY glPointSize (GLfloat size){

	Context * context  = getContext();

	if (context){
		context->PointSize = size;
	}
}
